//题目：
//输入一符串：
//规定，相邻的两个字符是可以相消的！ 但是，消除后，需要尽可能地消除剩余相邻地字符，使得字符尽可能短！
// abb -> a
// abba -> 0
// abbba -> aba
// abbbaaba -> 0
// bbbbb -> b
// 如果正好消完，直接打印"0"，反之打印消除后的结果


#include <iostream>
using namespace std;


//version 1 //超时了！！！！
int main() {
    string s;
    cin >> s;
    int left = 0, right = 0;
    while (right < s.size()) {
        if (right == 0 || s[right] != s[right - 1]) ++right;
        else {
            //此时就出现了两个可以相消除的字符
            //[left, right - 2]  [right - 1, right] [right + 1, s.size() - 1]
            //目前没有出现重复的区域 重复的两个字符 未扫描
            s = s.substr(0, right - 1 - left) + s.substr(right + 1);
            right -= 1;
        }
    }
    if (s == "") cout << "0" << endl;
    else cout << s << endl;
    return 0;
}

//第一种方法可行，但是容易超时！
//思路：
//right从前往后遍历字符串s，如果发现right前面的值(如果有)和当前right指向的值一样，那就把前面字串和后续的子串取出来合并回s
//如果和前面不一样，或者前面没有字符，就++right;
//直到right走到了s串的最后就停止

//这样就保证了数组可以被划分为三个部分(如果有连续两个重复字符)：
//[left, right - 2]  [right - 1, right] [right + 1, s.size() - 1]

//↓优化


//version 2
#include <iostream>
using namespace std;

int main() {
    string s;
    cin >> s;
    int left = -1, right = 0, n = s.size();
    while (right < n) {
        if (left == -1 || s[right] != s[left]) s[++left] = s[right++];
        else {
            ++right;
            --left;
        }
    }
    s = s.substr(0, left + 1);
    if (s == "") cout << "0" << endl;
    else cout << s << endl;
}


//思路1可以是可以，但是很容易超时，因为取子串substr的时候，其实隐藏了遍历！
//导致时间复杂度变为O(N)

//既然如此，我们发现数组是可以分区的！
//[0, left][重复元素][right, s.size()]
//这题就是双指针的思想！

//left指向的，就是没有重复的区间的最后一个元素！
//right从前往后走：
//如果发现s[right] != s[left]，说明此时s[right]属于没有重复的区间！加入该区间！ -> s[++left] = s[right++];
//但是，要是s[right] == s[left]，说明和最后一个重复了！ -> 进行抵消操作！
//所以，right往后移动一个位置。left往前移动一个位置，不就完成了抵消吗？
//left原本指向的位置被释放了！

//后序要是right还是能和left进行抵消，就继续上述的操作！


//本质上就是保证，[0, left]区间内是没有连续且重复的字符的！



///version3 题解视频   这题题就很像是用栈来做括号的匹配！
#include <stack> //或者扔到string内也可以的！  只不过是，使用栈的话，最后要把打印的次序逆过来，还是要借助string！
//所以，直接用string即可！
int main() {
    string s, st;
    cin >> s;

    for(int i = 0; i < s.size(); ++i){
        //如果栈为空，或者栈顶元素和当前的元素不一样 -> 入栈
        if(st.empty() || st.back() != s[i]) st += s[i];
        //要不然就是栈不为空 && 栈顶元素和当前遍历的元素是一样的！ -> 那就直接出栈
        else st.pop_back();
    }
    if(st == "") cout << "0" << endl;
    else cout << st << endl;
    return 0;
}
//但是很明显，version 2用双指针去写是可以极大降低空间复杂的！